home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
235_02
/
pathname.c
< prev
next >
Wrap
Text File
|
1987-06-16
|
13KB
|
326 lines
/* 003 14-Feb-87 pathname.c
Copyright (c) 1987 by Blue Sky Software. All rights reserved.
*/
#include "ov.h" /* only needed for Strdup() define */
#include "dosfile.h"
#ifndef NULL
#define NULL (0)
#endif
#ifndef MAX_PATHLEN
#define MAX_PATHLEN (64) /* max pathname len under MS/PC-DOS */
#endif
char *strupr(), *strrchr(), *strchr(), *qualdir();
struct search_block *nxtfile();
/****************************************************************************
P A R S E P A T H
****************************************************************************/
char *
parsepath(refdir,reffn,target,isdir,todirp,tofnp)
char *refdir, *reffn, *target, **todirp, **tofnp;
int isdir;
{
/* I don't know if this should really be called parsepath, but I couldn't
think of a better name. Here's what it does: given a reference
directory specification, a reference file name, and a traget name
(dir and/or file name) it creates a fully qualified target name
consisting of a drive specification and file name. One of the fancier
things this routine does (or has done) is expand relative dir spec's
(e.g. ..\ov) to fully qualified dir spec's (e.g. c:\src\ov). This
requires that the reference dir be fully qualified. parsepath()
will also return individual dir and/or file name strings if pointers
to char pointers are passed as todirp and tofnp. If one or both of
these strings are not desired, pass the value NULL instead of a
pointer address. All three of the parsepath() result strings are
in dynamically allocated memory that can be free'd with the free()
function.
Oh yea, the isdir parameter tells parsepath() if the target name
is just a dir name (isdir = true) or if it contains a file name
(and maybe a dir name) (isdir = false). This parameter was added
for performance - parsepath() doesn't need to call isadir() each
time if the caller already knows its not just a dir name.
Note: the refdir is used as if it were the current dir when qualifying
the target name. If the target contains no dir spec, the refdir spec
will be used. If the target contains a relative dir spec, the refdir
will be used as the starting point (a relative dir spec is relative to
the refdir).
BUT if the target contains a drive code that is different than the
drive code in refdir, parsepath() will call the external function
getcdir() to get the current dir spec for the target drive and use
that as the refdir instead of the passed refdir.
*/
char *tmp = NULL;
char *tardir, *tarfn, *np;
/* make sure both the reference dir and the target use \ instead of / */
fixdirspec(refdir); strupr(refdir); /* uppercase to make */
fixdirspec(target); strupr(target); /* compares easier */
/* determine if the target is on the same drive as the reference,
get a new reference dir if not */
if (strlen(target) > 1 && target[1] == ':') /* target have a drive? */
if (*refdir != *target) { /* different than ref? */
refdir = tmp = (char *) Malloc(MAX_PATHLEN+4); /* make new refdir */
strncpy(tmp,target,2);
tmp[2] = '\\';
getcdir(*target-'A'+1,tmp+3); /* sorta like getcwd() for drive */
}
/* determine if the target string has a directory and/or file name */
if (isdir) { /* is it only a dir (no file name)? */
tardir = Strdup(target);
tarfn = Strdup(reffn);
} else /* well is it a dir and file name? */
if ((np = strrchr(target,'\\')) || (np = strrchr(target,':'))) {
tardir = Strndup(target,np-target+1);
tarfn = Strdup(np+1);
} else { /* must be just a file name */
tardir = NULL;
tarfn = Strdup(target);
}
/* if a target dir was supplied, make sure its fully qualified */
if (tardir) {
np = tardir;
tardir = qualdir(refdir,tardir);
free(np);
} else
tardir = Strdup(refdir);
if (tmp) /* free locally allocated refdir string */
free(tmp);
/* make a copy of the fully qualified name for the user */
target = (char *) Malloc(strlen(tardir)+strlen(tarfn)+2);
strcpy(target,tardir);
if (target[strlen(target)-1] != '\\')
strcat(target,"\\");
strcat(target,tarfn);
/* return the seperate target dir/fn strings to user or release'm */
if (todirp)
*todirp = tardir;
else
free(tardir);
if (tofnp)
*tofnp = tarfn;
else
free(tarfn);
return(target); /* return the full target name */
}
/****************************************************************************
Q U A L D I R
****************************************************************************/
/* This routine expands a partial dir specification to a fully qualified
dir pathname. It requires a fully qualified refernece dir name and the
partial dir pathname. The reference dir spec is expected to start with
a drive code and end without a trailing '\'. The partial dir spec may
or may not contain a drive code, the qualified result will. If an error
is encountered, this routine returns a null string. */
char *
qualdir(refdir,partdir) /* fully qualify a partial dir spec */
char *refdir, *partdir;
{
register char *cp, *path;
char *psave, *sp, fullpath[MAX_PATHLEN+4];
/* setup the drive code of the resultant dir spec */
strncpy(fullpath,refdir,3); /* copy over "<drive>:\" */
fullpath[3] = '\0';
refdir += 3; /* don't need ref drive\root again */
if (strlen(partdir) > 1 && partdir[1] == ':') /* and don't really */
partdir += 2; /* need partial drive */
/* initialize the full pathname to the reference dir name if the partial
name doesn't start at the root */
if (*partdir == '\\') /* partial (relative) start at root? */
partdir++; /* already got \ above, don't need now */
else { /* must really be partial spec */
strcat(fullpath,refdir); /* start from reference dir */
if (fullpath[strlen(fullpath)-1] != '\\') /* we want trailing \ */
strcat(fullpath,"\\"); /* for now */
}
cp = fullpath + strlen(fullpath); /* always points to end of fullpath */
path = psave = Strdup(partdir); /* need a copy we can modify */
/* process the partial pathname a dir at a time - still more to do
while path has something in it */
while(strlen(path)) {
if (sp = strchr(path,'\\')) /* find end of current dir name */
*sp = '\0'; /* null terminate it */
if (strcmp(path,".") == 0) /* "." entry is current dir */
; /* so there is nowhere to go */
else
if (strcmp(path,"..") == 0) { /* ".." means goto parent dir */
*--cp = '\0'; /* zap trailing \ */
if (cp = strrchr(fullpath,'\\')) /* find \ before current */
*++cp = '\0'; /* zap curr - parent now last */
else { /* error, no more parents! */
*fullpath = '\0'; /* return null string */
break; /* stop processing */
}
} else /* not "." or "..", must be subdir name */
if (strlen(fullpath) + strlen(path) < sizeof(fullpath)) { /* fit? */
strcpy(cp,path);
strcat(cp,"\\"); /* add subdir to fullpath */
cp += strlen(cp);